<!--
 * @Author       : wfl
 * @LastEditors: fj
 * @description  : 全局列表组件
 * @updateInfo   :
 * @Date         : 2022-11-22 11:09:21
 * @LastEditTime: 2023-09-08 14:52:02
-->
<script lang="ts" setup name="IkItemList">
import { _ } from 'iking-utils'
import type { PropType } from 'vue'
import { ElMessageBox } from 'element-plus'

const props = defineProps({
  // 列表数据
  list: {
    type: Array as PropType<Array<Tlist>>,
    default: () => []
  },
  // 字段映射
  proxy: {
    type: Object as PropType<{ label: string; value: string; }>,
    default: () => {
      return {
        label: 'label',
        value: 'value'
      }
    }
  },
  // 是否显示搜索栏
  search: {
    type: Boolean,
    default: true
  },
  // 默认选中第一条
  immediate: {
    type: Boolean,
    default: true
  },
  // 是否使用tab模式
  tab: {
    type: Boolean,
    default: false
  },
  // 是否显示数量
  isCount: {
    type: Boolean,
    default: false
  },
  // padding值
  padding: {
    type: String,
    default: '0 12px'
  },
  // 是否确认离开
  confirmLeave: {
    type: Boolean,
    default: false
  },
  confirmLeaveText: {
    type: String,
    default: '当前配置未保存，是否确定切换？'
  },
  confirmBtnText: {
    type: String,
    default: '确定切换'
  }
})

const emits = defineEmits<{
  (e: 'select', item: any, index: number): void
  (e: 'confirm', item: any, index: number): void
}>()

const DEFAULT_PROXY = {
  label: 'label',
  value: 'value',
  count: 'count'
}

interface Tlist {
  label: string
  value: any
  [key: string]: any
}
const mergeProp = {
  ...DEFAULT_PROXY,
  ...props.proxy
}

const state: {
  cloneList: Tlist[]
  activeValue: string
} = reactive({
  cloneList: [],
  activeValue: ''
})

const handSelect = (item: Tlist, index: number) => {
  if (props.confirmLeave) {
    ElMessageBox.confirm(props.confirmLeaveText, '温馨提醒', {
      confirmButtonText: props.confirmBtnText,
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        state.activeValue = item[mergeProp.value]
        emits('select', item, index)
      })
      .catch(() => {})
  }
  else {
    emits('select', item, index)
    state.activeValue = item[mergeProp.value]
  }
}
const handSelectTab = (num: any) => {
  const item = props.list.find(v => v.id === num) || null
  const index = props.list.findIndex(v => v.id === num)
  item && handSelect(item, index)
}

watch(
  () => props.list,
  val => {
    state.cloneList = val
    // 为了解决在 el-tab模式下，数组更新后，tab并没有更改视图的bug
    state.activeValue = ''
    if (props.immediate) {
      nextTick(() => {
        state.activeValue = val?.[0]?.[mergeProp.value]
        emits('select', val?.[0], 0)
      })
    }
  },
  { deep: true }
)

const handFilter = (text: string) => {
  if (!text)
    state.cloneList = _.cloneDeep(props.list)

  state.cloneList = props.list.filter(item =>
    item[mergeProp.label].toLocaleUpperCase().includes(text.toLocaleUpperCase())
  )
}
const _handFilter = _.throttle(handFilter, 200)
const filterText = ref('')
watch(filterText, val => {
  _handFilter(val)
})

defineExpose({
  handSelect
})
</script>

<template>
  <div class="ik-item-list overflow-overlay" :style="{ padding }">
    <el-input
      v-if="search"
      v-model.trim="filterText"
      clearable
      placeholder="请输入关键字检索"
    >
      <!-- <template #append>
        <IkSvgIcon name="iksvg_sousuo-daohang" />
      </template> -->
    </el-input>
    <!-- el-tab模式 -->
    <el-tabs
      v-if="tab"
      v-model="state.activeValue"
      tab-position="left"
      class="flex-1 h-full"
      @tab-change="handSelectTab"
    >
      <el-tab-pane
        v-for="(item, index) in state.cloneList"
        :key="item.id"
        :name="item.id"
      >
        <template #label>
          <div class="text-over-line" :class="{ 'count-line': isCount }">
            <slot name="prefix" :item="{ ...item, index }"></slot>
            <!-- 根据是否存在名为item的slot判断显示默认样式或自定义 -->
            <template v-if="$slots.item">
              <slot name="item" :item="{ ...item, index }"></slot>
            </template>
            <template v-else>
              <div
                :class="{ 'had-prefix': $slots.prefix, 'count-line': isCount }"
                :title="item[mergeProp.label]"
                class="text-over-line"
              >
                {{ item[mergeProp.label] }}
              </div>
              <div v-if="isCount" class="badge">
                {{
                  Number(item[mergeProp.count]) > 99
                    ? '99+'
                    : item[mergeProp.count]
                }}
              </div>
            </template>
          </div>
          <slot name="suffix" :item="{ ...item, index }"></slot>
        </template>
      </el-tab-pane>
    </el-tabs>
    <ul v-else class="gl-item-list">
      <div class="active-line"></div>
      <template v-if="state.cloneList.length">
        <li
          v-for="(item, index) in state.cloneList"
          :key="item[mergeProp.value]"
          :class="{ active: state.activeValue === item[mergeProp.value] }"
          @click="handSelect(item, index)"
        >
          <div :class="{ 'count-line': isCount }" class="text-over-line">
            <slot name="prefix" :item="{ ...item, index }"></slot>
            <!-- 根据是否存在名为item的slot判断显示默认样式或自定义 -->
            <slot
              v-if="$slots.item"
              name="item"
              :item="{ ...item, index }"
            ></slot>
            <div
              v-else
              :class="{ 'had-prefix': $slots.prefix, 'count-line': isCount }"
              :title="item[mergeProp.label]"
              class="text-over-line"
            >
              {{ item[mergeProp.label] }}
            </div>
            <div v-show="isCount" class="badge">
              {{
                Number(item[mergeProp.count]) > 99
                  ? '99+'
                  : item[mergeProp.count]
              }}
            </div>
          </div>
          <slot name="suffix" :item="{ ...item, index }"></slot>
        </li>
      </template>
      <template v-else>
        <IkEmpty />
      </template>
    </ul>
  </div>
</template>

<style lang="scss" scoped>
.ik-item-list {
  height: calc(100% - var(--ik-card-header-height, 72px));
  display: flex;
  flex-direction: column;

  .ik-bianji {
    color: var(--el-color-primary);

    &:hover {
      color: var(--el-color-primary-light-3);
    }
  }

  .ik-shanchu1 {
    color: var(--el-color-danger-light-3);

    &:hover {
      color: var(--el-color-danger);
    }
  }

  :deep(.el-tabs) {
    --el-tabs-header-height: 24px;

    .el-tabs__nav-prev,.el-tabs__nav-next{
      display: none;
    }

    .el-tabs__nav.is-left {
      width: 100%;
      overflow: hidden auto;
      height: 100%;
      display: block;
    }

    .el-tabs__header.is-left {
      width: 100%;
      margin-right: 0;

      .el-tabs__item {
        // height: 40px;
        box-sizing: content-box;
        padding: 11px 8px;
        text-align: left;
        display: flex;
        justify-content: space-between;
        margin: 8px 0;
        align-items: center;
        transition: all 0.25s ease-in-out;

        &:hover {
          color: var(--el-color-primary);
        }

        &.is-active {
          border-right-color: var(--el-color-primary);
          color: var(--el-color-primary);
          background: var(--el-color-primary-light-9);
        }
      }
    }

    &.el-tabs--left {
      .el-tabs__active-bar.is-left {
        width: 4px;
      }

      .el-tabs__nav-wrap.is-left::after {
        display: none;
      }
    }
  }

  .gl-item-list {
    height: calc(100% - var(--el-component-size, 40px));
    overflow: auto;
    margin-right: calc(-1 * var(--ik-scrollbar-width));

    li {
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-right: 4px solid transparent;
      transition: all 0.3s ease-in-out;
      font-size: var(--el-font-size-base);
      padding: 9px 8px;
      margin: 8px 0;

      &:hover {
        color: var(--el-color-primary);
      }

      &.active {
        border-right-color: var(--el-color-primary);
        color: var(--el-color-primary);
        background: var(--el-color-primary-light-9);
      }

      .count-line {
        display: flex;
        align-items: center;

        .had-prefix {
          padding-left: var(--base-p);
        }
      }
    }
  }
}

.count-line {
  width: 100%;

  .badge {
    padding: 0 8px;
    border-radius: 8px;
    background: red;
    color: #fff;
    text-align: center;
    font-size: 12px;
  }
}
</style>
